﻿using System;
using System.Collections;
using System.Reflection;
using System.Xml;

namespace QQ2564874169.Tencent.Weixin
{
    public abstract class WXEntity
    {
        private XmlDocument _xml;

        protected virtual string GetRootName()
        {
            return "xml";
        }

        protected virtual XmlNode GetNode(string name, object value)
        {
            if (value == null) return null;
            var node = _xml.CreateElement(name);
            var etx = value as WXEntity;

            if (etx != null)
            {
                var xml = etx.ToXml();
                if (xml.DocumentElement != null)
                {
                    node.InnerXml = xml.DocumentElement.InnerXml;
                }
            }
            else if (value is int)
            {
                node.InnerXml = FormatValue(value);
            }
            else if (value is bool)
            {
                node.InnerXml = FormatValue(((bool) value) ? 1 : 0);
            }
            else if (value is DateTime)
            {
                node.InnerXml = ((DateTime)value).ToLongTime().ToString();
            }
            else if (value is Enum)
            {
                node.InnerXml = FormatValue(value);
            }
            if (string.IsNullOrEmpty(node.InnerXml))
            {
                node.InnerXml = FormatValue(value);
            }
            return node;
        }

        private static string FormatValue(object value)
        {
            return "<![CDATA[" + value + "]]>";
        }

        public virtual XmlDocument ToXml()
        {
            _xml = new XmlDocument();
            var ps = GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
            var root = _xml.CreateElement(GetRootName());
            _xml.AppendChild(root);

            foreach (var p in ps)
            {
                var v = p.GetValue(this, null);
                if (v != null)
                {
                    var items = new ArrayList();
                    if (v is ICollection)
                    {
                        items.AddRange(v as ICollection);
                    }
                    else
                    {
                        items.Add(v);
                    }
                    foreach (var item in items)
                    {
                        var node = GetNode(p.Name, item);
                        if (node != null)
                            root.AppendChild(node);
                    }
                }
            }
            return _xml;
        }
    }
}